#include "render.h"

namespace SkyID
{

//- Render --------------------------------------------------------------------

namespace Render
{

static RenderState gRenderState;

bool initialize(const Config &config)
{
	// setup viewport
	glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0.0, (double)Window::getWidth(), (double)Window::getHeight(), 0.0, -1.0, 1.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	// enable what we need
	glEnable(GL_TEXTURE_2D);
	gRenderState.enableTexture = true;
	glEnable(GL_BLEND);
	gRenderState.enableBlend = true;

	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	gRenderState.enableTextureCoordArray = true;
	glEnableClientState(GL_VERTEX_ARRAY);
	gRenderState.enableVertexArray = true;

	// disable
	glDisable(GL_DEPTH_TEST);
	gRenderState.enableDepthTest = false;

	// other stuff
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	gRenderState.textureID = 0;

	LOG_MSG("Render: initialized");
	return true;
}

void shutdown()
{
	LOG_MSG("Render: shutdown");
}

void beginScene()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glLoadIdentity();
}

void endScene()
{
	Window::swapBuffers();
}

void setTextureEnbale(bool enable)
{
	if (enable && !gRenderState.enableTexture)
	{
		glEnable(GL_TEXTURE_2D);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	} else if (!enable && gRenderState.enableTexture)
	{
		glDisable(GL_TEXTURE_2D);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	}
	gRenderState.enableTexture = enable;
	gRenderState.enableTextureCoordArray = enable;
}

void bindTexture(const Texture *texture)
{
	LOG_ASSERT(texture);

	setTextureEnbale(true);
	if (gRenderState.textureID != texture->getID())
	{
		glBindTexture(texture->getTarget(), texture->getID());
		gRenderState.textureID = texture->getID();
	}
}

void setColor(const Color &color)
{
	glColor4fv(color.c);
}

void renderVertices(GLenum mode, const Vertex* v, uint32 n)
{
	LOG_ASSERT(v);

	if (gRenderState.enableVertexArray)
	{
		if (gRenderState.enableTextureCoordArray && gRenderState.enableTexture)
			glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), v->t);
		glVertexPointer(2, GL_FLOAT, sizeof(Vertex), v->c);
		glDrawArrays(mode, 0, n);
	} else
	{
		glBegin(mode);
		for (uint32 i=0; i<n; ++i)
		{
			if (gRenderState.enableTexture)
				glTexCoord2fv((v+i)->t);
			glVertex2fv((v+i)->c);
		}
		glEnd();
	}
}

void renderSprite(const Sprite *sprite, float x, float y, float w, float h)
{
	LOG_ASSERT(sprite);

	if (w == 0.0f)
		w = sprite->getWidth();
	if (h == 0.0f)
		h = sprite->getHeight();

	Vertex v[4];
	v[0].x = x;
	v[0].y = y;
	v[1].x = x+w;
	v[1].y = y;
	v[2].x = x+w;
	v[2].y = y+h;
	v[3].x = x;
	v[3].y = y+h;

	const Rect *rect = sprite->getTextureRect();
	v[0].u = rect->p1.x;
	v[0].v = rect->p1.y;
	v[1].u = rect->p2.x;
	v[1].v = rect->p1.y;
	v[2].u = rect->p2.x;
	v[2].v = rect->p2.y;
	v[3].u = rect->p1.x;
	v[3].v = rect->p2.y;

	bindTexture(sprite->getTexture());
	renderVertices(GL_QUADS, v, 4);
}

} // namespace Render

} // namespace SkyID
